import os
import difflib
import filecmp
import shutil
from pathlib import Path
from datetime import datetime
import html
from diff_match_patch import diff_match_patch
from config import *

class CodeDiffTool:
    def __init__(self, before_dir=BEFORE_FOLDER, after_dir=AFTER_FOLDER, diff_dir=DIFF_FOLDER):
        self.before_dir = Path(before_dir)
        self.after_dir = Path(after_dir)
        self.diff_dir = Path(diff_dir)
        self.stats = {
            'total_files': 0,
            'changed_files': 0,
            'added_lines': 0,
            'removed_lines': 0,
            'modified_lines': 0
        }
        self.changed_files_list = []  # 用于导航

    def ensure_directories(self):
        self.diff_dir.mkdir(exist_ok=True)

    def is_code_file(self, file_path):
        return file_path.suffix.lower() in CODE_EXTENSIONS

    def find_code_files(self, directory):
        code_files = []
        for root, _, files in os.walk(directory):
            for file in files:
                file_path = Path(root) / file
                if self.is_code_file(file_path):
                    code_files.append(file_path)
        return code_files

    def get_relative_path(self, file_path):
        try:
            if str(file_path).startswith(str(self.before_dir)):
                return file_path.relative_to(self.before_dir)
            elif str(file_path).startswith(str(self.after_dir)):
                return file_path.relative_to(self.after_dir)
        except ValueError:
            pass
        return file_path

    def compare_files(self, before_file, after_file):
        try:
            with open(before_file, 'r', encoding='utf-8') as f1, \
                 open(after_file, 'r', encoding='utf-8') as f2:
                before_lines = f1.readlines()
                after_lines = f2.readlines()
            return before_lines, after_lines
        except Exception as e:
            print(f"[读取错误] {before_file} 或 {after_file}: {e}")
            return [], []

    def generate_side_by_side_with_char_diff(self, filename, before_lines, after_lines, relative_path):
        dmp = diff_match_patch()
        html_rows = []
        before_line_num = 1
        after_line_num = 1

        if before_lines == after_lines:
            return self._generate_unchanged_file_report(filename, relative_path)

        for before_line, after_line in zip(before_lines, after_lines):
            if before_line == after_line:
                html_rows.append({
                    'type': 'unchanged',
                    'before': before_line.rstrip(),
                    'after': after_line.rstrip(),
                    'before_line': before_line_num,
                    'after_line': after_line_num
                })
                before_line_num += 1
                after_line_num += 1
            else:
                diffs = dmp.diff_main(before_line.rstrip(), after_line.rstrip())
                dmp.diff_cleanupSemantic(diffs)
                before_html = self._build_segmented_line(diffs)
                html_rows.append({
                    'type': 'modified',
                    'before': before_line.rstrip(),
                    'after': after_line.rstrip(),
                    'before_html': before_html,
                    'before_line': before_line_num,
                    'after_line': after_line_num
                })
                before_line_num += 1
                after_line_num += 1

        self.changed_files_list.append(str(relative_path))
        html_content = self._generate_side_by_side_html(filename, html_rows, relative_path)
        return html_content

    def _build_segmented_line(self, diffs):
        html_line = ""
        for op, text in diffs:
            if op == -1:  # 删除
                html_line += f'<span style="background-color: #ffcccc; text-decoration: line-through;">{html.escape(text)}</span>'
            elif op == 1:  # 新增
                html_line += f'<span style="background-color: #ccffcc;">{html.escape(text)}</span>'
            else:  # 相等
                html_line += html.escape(text)
        return html_line

    def _generate_side_by_side_html(self, filename, rows, relative_path):
        html_content = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>代码对比 - {filename}</title>
            <style>
                body {{ font-family: Consolas, monospace; margin: 20px; background: #f4f4f4; }}
                .container {{ max-width: 1400px; margin: auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }}
                .header {{ border-bottom: 2px solid #000; margin-bottom: 20px; }}
                .file-info {{ color: #666; margin-bottom: 10px; }}
                .stats {{ background: #eee; padding: 10px; border-radius: 5px; margin-bottom: 20px; }}
                .summary-item {{ display: inline-block; margin-right: 15px; font-weight: bold; }}
                .summary-modified {{ color: orange; }}
                .code-container {{ display: flex; border: 1px solid #ccc; border-radius: 5px; overflow: hidden; }}
                .code-panel {{ flex: 1; padding: 15px; font-size: 14px; line-height: 1.5; background: #f9f9f9; }}
                .code-panel:before {{ content: "{filename} (BEFORE)"; font-weight: bold; background: #ddd; padding: 5px 10px; margin: -15px -15px 10px -15px; display: block; font-size: 13px; }}
                .code-panel:last-child:before {{ content: "{filename} (AFTER)"; }}
                .line {{ display: flex; border-bottom: 1px solid #ddd; }}
                .line:last-child {{ border-bottom: none; }}
                .line-number {{ color: #888; width: 40px; text-align: right; padding-right: 10px; font-size: 12px; user-select: none; }}
                .line-content {{ flex: 1; white-space: pre-wrap; }}
                .line-modified {{ background-color: #f0f0f0; }}
                .export-md {{ margin-top: 10px; }}
                .export-md a {{ color: blue; text-decoration: underline; }}
            </style>
        </head>
        <body>
            <div class="container">
                <div class="header">
                    <h1>代码对比报告</h1>
                    <div class="file-info">文件: {relative_path}</div>
                    <div class="file-info">对比时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</div>
                </div>

                <div class="stats">
                    <div class="summary-item summary-modified">修改: 1 行（字符级 diff）</div>
                </div>

                <div class="code-container">
                    <div class="code-panel">
                        {self._generate_panel_with_html(rows, 'before')}
                    </div>
                    <div class="code-panel">
                        {self._generate_panel_with_html(rows, 'after')}
                    </div>
                </div>

                <div class="export-md">
                    <a href="#" onclick="alert('Markdown 导出功能开发中...'); return false;">📄 导出为 Markdown</a>
                </div>
            </div>
        </body>
        </html>
        """
        return html_content

    def _generate_panel_with_html(self, rows, panel):
        content = ""
        for row in rows:
            if panel == 'before':
                if row['type'] == 'modified':
                    content += f'<div class="line line-modified"><span class="line-number">{row["before_line"]}</span><span class="line-content">{row["before_html"]}</span></div>'
                else:
                    content += f'<div class="line"><span class="line-number">{row.get("before_line", "")}</span><span class="line-content">{html.escape(row.get("before", ""))}</span></div>'
            elif panel == 'after':
                if row['type'] == 'modified':
                    content += f'<div class="line line-modified"><span class="line-number">{row["after_line"]}</span><span class="line-content">{row["before_html"] if "before_html" in row else row.get("after_html", "")}</span></div>'  # 需要调整
                else:
                    content += f'<div class="line"><span class="line-number">{row.get("after_line", "")}</span><span class="line-content">{html.escape(row.get("after", ""))}</span></div>'
        return content

    def _generate_unchanged_file_report(self, filename, relative_path):
        html_content = f"""
        <!DOCTYPE html>
        <html>
        <head><title>代码对比 - {filename}</title></head>
        <body>
            <h1>代码对比报告</h1>
            <p>文件 <strong>{relative_path}</strong> 未发生变化。</p>
        </body>
        </html>
        """
        path_obj = Path(relative_path)
        output_dir = self.diff_dir / path_obj.parent
        output_dir.mkdir(parents=True, exist_ok=True)
        html_filename = path_obj.stem + '_diff.html'
        html_path = output_dir / html_filename
        with open(html_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        return html_content

    def create_diff_report(self, relative_path, before_file, after_file):
        filename = relative_path.name if hasattr(relative_path, 'name') else relative_path
        print(f"正在比较文件: {filename}")

        before_path = self.before_dir / relative_path
        after_path = self.after_dir / relative_path

        if not before_path.exists():
            print(f"警告: 文件 {before_path} 不存在于 before 文件夹中")
            return
        if not after_path.exists():
            print(f"警告: 文件 {after_path} 不存在于 after 文件夹中")
            return

        before_lines, after_lines = self.compare_files(before_path, after_path)

        if before_lines == after_lines:
            print(f"文件未变化: {filename}")
            return

        html_content = self.generate_side_by_side_with_char_diff(filename, before_lines, after_lines, relative_path)

        path_obj = Path(relative_path)
        output_dir = self.diff_dir / path_obj.parent
        output_dir.mkdir(parents=True, exist_ok=True)

        html_filename = path_obj.stem + '_diff.html'
        html_path = output_dir / html_filename

        with open(html_path, 'w', encoding='utf-8') as f:
            f.write(html_content)

        print(f"已生成对比报告: {html_path}")

        self.stats['total_files'] += 1
        self.stats['changed_files'] += 1

    def generate_file_tree_navigation(self):
        nav_content = "<h2>📁 文件对比导航</h2><ul>"
        for f in set(self.changed_files_list):
            safe_name = f.replace('/', '_').replace('\\', '_')
            nav_content += f'<li><a href="{f}_diff.html">{f}</a></li>'
        nav_content += "</ul>"

        nav_html = f"""
        <!DOCTYPE html>
        <html>
        <head><title>🔍 文件对比导航</title></head>
        <body>
            <h1>🔍 代码对比 - 文件导航</h1>
            {nav_content}
        </body>
        </html>
        """

        nav_path = self.diff_dir / "index.html"
        with open(nav_path, 'w', encoding='utf-8') as f:
            f.write(nav_html)
        print(f"✅ 文件导航已生成: {nav_path}")

    def run_comparison(self):
        self.ensure_directories()

        before_files = self.find_code_files(self.before_dir)
        after_files = self.find_code_files(self.after_dir)

        print(f"在 before 文件夹中找到 {len(before_files)} 个代码文件")
        print(f"在 after 文件夹中找到 {len(after_files)} 个代码文件")

        before_rel_paths = set()
        for f in before_files:
            rel = self.get_relative_path(f)
            before_rel_paths.add(rel)

        after_rel_paths = set()
        for f in after_files:
            rel = self.get_relative_path(f)
            after_rel_paths.add(rel)

        common_paths = before_rel_paths.intersection(after_rel_paths)
        for relative_path in common_paths:
            before_file = self.before_dir / relative_path
            after_file = self.after_dir / relative_path
            self.create_diff_report(relative_path, before_file, after_file)

        only_before = before_rel_paths - after_rel_paths
        for relative_path in only_before:
            before_file = self.before_dir / relative_path
            self.stats['changed_files'] += 1
            output_dir = self.diff_dir / relative_path.parent
            output_dir.mkdir(parents=True, exist_ok=True)

            html_content = f"""
            <!DOCTYPE html>
            <html>
            <head><title>文件已删除 - {relative_path}</title></head>
            <body>
                <h1>🗑️ 文件已删除</h1>
                <p>文件 <strong>{relative_path}</strong> 在 after 文件夹中不存在，可能已被删除。</p>
                <p>原文件路径: {before_file}</p>
                <p>对比时间: {datetime.now()}</p>
            </body>
            </html>
            """

            html_path = output_dir / (relative_path.stem + '_deleted.html')
            with open(html_path, 'w', encoding='utf-8') as f:
                f.write(html_content)
            print(f"✅ 已生成删除报告: {html_path}")

        only_after = after_rel_paths - before_rel_paths
        for relative_path in only_after:
            after_file = self.after_dir / relative_path
            self.stats['changed_files'] += 1
            output_dir = self.diff_dir / relative_path.parent
            output_dir.mkdir(parents=True, exist_ok=True)

            html_content = f"""
            <!DOCTYPE html>
            <html>
            <head><title>文件已新增 - {relative_path}</title></head>
            <body>
                <h1>➕ 文件已新增</h1>
                <p>文件 <strong>{relative_path}</strong> 在 before 文件夹中不存在，可能为新增文件。</p>
                <p>新文件路径: {after_file}</p>
                <p>对比时间: {datetime.now()}</p>
            </body>
            </html>
            """

            html_path = output_dir / (relative_path.stem + '_added.html')
            with open(html_path, 'w', encoding='utf-8') as f:
                f.write(html_content)
            print(f"✅ 已生成新增报告: {html_path}")

        self.generate_file_tree_navigation()
        self.generate_summary_report()

    def generate_summary_report(self):
        summary_path = self.diff_dir / "SUMMARY_REPORT.html"
        summary_html = f"""
        <!DOCTYPE html>
        <html>
        <head><title>📊 对比总结报告</title></head>
        <body>
            <h1>📊 代码对比总结报告</h1>
            <p>总文件数: {self.stats['total_files']}</p>
            <p>有变化的文件数: {self.stats['changed_files']}</p>
            <p>生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
            <p>🔗 查看所有对比: <a href="index.html">文件导航</a></p>
        </body>
        </html>
        """
        with open(summary_path, 'w', encoding='utf-8') as f:
            f.write(summary_html)
        print(f"✅ 总结报告已生成: {summary_path}")

def main():
    tool = CodeDiffTool()
    tool.run_comparison()

if __name__ == "__main__":
    main()